const amqp_cfg = configure.get('amqp')
const service_reg = require('../../../service/dao/serviceReg')

const im_suffix = amqp_cfg.im_suffix || ''
const im_iot_queue = amqp_cfg.im_iot_queue + im_suffix
const im_task_queue = amqp_cfg.im_task_queue + im_suffix

const socketUtil = require('../socket.io/socketUtil')
const sms = require('../../../service/common/alicloud/sms')
const vms = require('../../../service/common/alicloud/vms')
const jpush = require('../../../service/common/jpush/jpush')

const emitMessage = socketUtil.emitMessage
const messageBuilder = socketUtil.messageBuilder
const redisCfg = configure.get('redis')
const redisClient = require('redis').createClient(redisCfg)
const io = require('socket.io-emitter')(redisClient)

const amqp = require('amqp-connection-manager')
const connection = amqp.connect([amqp_cfg.url])

const amqpRPC = require('amqp-connection-manager-rpcx')
const connectionRPC = amqpRPC.connect([amqp_cfg.url], { json: true })

connectionRPC.on('connect', function () {
    log4js.debug('RPC Server connection Connected!')
})
connectionRPC.on('disconnect', function (params) {
    log4js.error('RPC Server connection Disconnected.', params.err.stack)
})

const start = () => {
    // im_iot_queue 事件消息队列转发
    connection.createChannel({
        json: true,
        setup: async (ch) => {
            await ch.assertQueue(im_iot_queue);
            await ch.prefetch(100);
            return ch.consume(im_iot_queue, async (msg) => {
                if (msg !== null) {
                    log4js.debug(msg.content.toString())

                    let _content = JSON.parse(msg.content.toString())

                    let device_id = _.get(_content, 'device_id') || ''
                    log4js.debug('receive device msg, device_id=', device_id)

                    let _cur_unit_id = _.get(_content, 'unit_id') || _.get(_content, 'content.device.unitId') || ''
                    let _cur_region_code = _.get(_content, 'region_code') || _.get(_content, 'content.device.regionCode') || ''
                    let _cur_device_id = device_id
                    let _cur_event_id = _.get(_content, 'type_code') || ''

                    let _services = await service_reg.regList()

                    for (let si = 0; si < _services.length; si++) {
                        let item = _services[si]

                        let _cur = [[0, _cur_unit_id], [1, _cur_device_id], [2, _cur_event_id], [3, _cur_region_code]]

                        let _is_include = false
                        for (let ii = 0; ii < item.list.length; ii++) {
                            let it = item.list[ii]
                            let _item_unit_id = _.get(it, 'unit_id') || ''
                            let _item_device_id = _.get(it, 'device_id') || ''
                            let _item_event_id = _.get(it, 'event_id') || ''
                            let _item_region_code = _.get(it, 'region_code') || ''

                            let _item = [[0, _item_unit_id], [1, _item_device_id], [2, _item_event_id], [3, _item_region_code]]

                            // log4js.debug('app_name=', _.get(item, 'app_name'), ',_cur=', _cur, ',_item=', _item)
                            if (helper.includes(_cur, _item)) {
                                _is_include = true
                                break
                            }
                        }

                        let _socket_id = _.get(item, 'client_ids.0') || ''
                        if (_is_include && !!_socket_id) {
                            // 支持多主情况下选主一个触发
                            await emitMessage(io, _socket_id, messageBuilder(1000, {
                                ..._content,
                                unit_id: _cur_unit_id,
                                device_id: _cur_device_id,
                                event_id: _cur_event_id,
                                region_code: _cur_region_code,
                            }, _.get(item, 'app_name') || ''))
                        }
                    }
                }
            }, { noAck: true })
        }
    })

    connectionRPC.createRPCServer(im_task_queue, async (_content) => {
        log4js.debug('rpc server receive msg: ', JSON.stringify(_content))

        let task_id = _.get(_content, 'id')
        let way_code = _.get(_content, 'way.way_code') || ''

        // 短信和语音
        if (way_code === 'PROVIDER_ALI_CLOUD_SMS' || way_code === 'PROVIDER_ALI_CLOUD_MNS') {
            let _way_info = await dbUtil.getRow('dic_notice_way', { way_code: way_code })

            let notice_receiver = _.uniq(_.get(_content, 'notice_receiver') || [])
            let content_type = _.get(_content, 'content_type')
            let content = _.get(_content, 'content')

            let sign_name = _.get(_content, 'way.sign_name') || ''
            let template_code = _.get(_content, 'way.template_code') || ''                              // 基础平台中的模板
            let template_code_rel = _.get(_content, 'way.template_code_rel') || template_code || ''     // 第三方账号模板

            // 转换签名 - 适用于私有化部署
            if (sign_name) {
                let _sign_info = await dbUtil.getRow('dic_notice_sign', {
                    is_enable: 1,
                    is_delete: 1,
                    provider_code: _way_info.provider_code,
                    way_code: _way_info.way_code,
                    sign_name: sign_name,
                })

                if (_sign_info) {
                    sign_name = _sign_info.sign_name_parse || _sign_info.sign_name
                }
            }

            // 转换模板 - 适用于私有化部署
            if (template_code) {
                let _template_info = await dbUtil.getRow('dic_notice_template', {
                    is_enable: 1,
                    is_delete: 1,
                    provider_code: _way_info.provider_code,
                    way_code: _way_info.way_code,
                    template_code: template_code,
                })

                if (_template_info) {
                    template_code = _template_info.template_code_parse || _template_info.template_code;
                    template_code_rel = template_code_rel || template_code;

                    if(!!_template_info.content) { // 提纯模板变量
                        let keys = _template_info.content.match(/[^\{\}]+(?=\})/g);
                        if(keys.length) {
                            content = _.pick(content, keys);
                            keys.map(_k => {
                                if (content[_k] && content[_k].length > 20) {
                                    content[_k] = content[_k].substr(0, 19)
                                }
                            })
                        }
                    }
                }
            }

            await Promise.all(notice_receiver.map(async receiver => {
                try {
                    let id = helper.uuid()
                    await M('notice_task_detail').create({
                        id: id,
                        notice_task_id: task_id,
                        notice_receiver: receiver,
                        org_id: _.get(_content, 'org_id'),
                        service_info: _.get(_content, 'service_info'),
                        way: _.get(_content, 'way'),
                        send_status: {
                            code: 1,
                            message: '初始化'
                        },
                        confirm_status: {
                            code: 1,
                            message: '初始化'
                        },
                        content_type: content_type,
                    })

                    try {

                        let _args = {
                            app_key: _.get(_content, 'way.app_key') || _way_info.app_key || '',
                            app_secret: _.get(_content, 'way.app_secret') || _way_info.app_secret || '',
                            sign_name: sign_name,
                            template_code: template_code_rel,
                            content,
                        }
                        if (way_code === 'PROVIDER_ALI_CLOUD_SMS') {
                            await sms.send(receiver, _args)
                        } else {
                            await vms.send(receiver, _args)
                        }

                        await M('notice_task_detail').updateOne({
                            id: id,
                        }, {
                            $set: {
                                send_status: {
                                    code: 2,
                                    message: '发送成功'
                                }
                            }
                        })
                    } catch (err) {
                        await M('notice_task_detail').updateOne({
                            id: id,
                        }, {
                            $set: {
                                send_status: {
                                    code: 3,
                                    message: err.message
                                }
                            }
                        })

                        log4js.error(err)
                    }
                } catch (e) {
                    log4js.debug(e)
                }
            }))
        } else if (way_code === 'PROVIDER_JI_PUSH_SOCKET') { // 极光推送
            let _way_info = await dbUtil.getRow('dic_notice_way', { way_code: way_code })

            let notice_receiver = _.get(_content, 'notice_receiver') || []
            let content_type = _.get(_content, 'content_type')
            let content = _.get(_content, 'content')
            await Promise.all(notice_receiver.map(async receiver => {
                try {
                    let id = helper.uuid()
                    await M('notice_task_detail').create({
                        id: id,
                        notice_task_id: task_id,
                        notice_receiver: receiver,
                        send_status: {
                            code: 1,
                            message: '初始化'
                        },
                        confirm_status: {
                            code: 1,
                            message: '初始化'
                        },
                        content_type: content_type,
                    })

                    try {
                        await jpush.send(receiver, {
                            app_key: _.get(_content, 'way.app_key') || _way_info.app_key || '',
                            app_secret: _.get(_content, 'way.app_secret') || _way_info.app_secret || '',
                            content,
                        })

                        await M('notice_task_detail').updateOne({
                            id: id,
                        }, {
                            $set: {
                                send_status: {
                                    code: 2,
                                    message: '发送成功'
                                }
                            }
                        })
                    } catch (err) {
                        await M('notice_task_detail').updateOne({
                            id: id,
                        }, {
                            $set: {
                                send_status: {
                                    code: 3,
                                    message: err.message
                                }
                            }
                        })

                        log4js.error(err)
                    }
                } catch (e) {
                    log4js.error(e)
                }
            }))
        } else if (way_code === 'IM_WEBSOCKET') { // IM 支持的websocket
            let notice_receiver = _.get(_content, 'notice_receiver') || []
            let content_type = _.get(_content, 'content_type')
            let content = _.get(_content, 'content')
            await Promise.all(notice_receiver.map(async receiver => {
                try {
                    let id = helper.uuid()
                    await M('notice_task_detail').create({
                        id: id,
                        notice_task_id: task_id,
                        notice_receiver: receiver,
                        send_status: {
                            code: 1,
                            message: '初始化'
                        },
                        confirm_status: {
                            code: 1,
                            message: '初始化'
                        },
                        content_type: content_type,
                    })

                    let _cli = await dbUtil.getRow('im_client_socket', {
                        im_suffix: im_suffix,
                        user_id: receiver,
                        product: (_.get(_content, 'service_info.app_name') || '').split('_')[0]
                    })

                    if (_cli) {
                        await emitMessage(io, `${receiver}_web`, messageBuilder(1000, content, receiver))
                        await emitMessage(io, `${_cli.socket_id_android}`, messageBuilder(1000, content, receiver))
                        await emitMessage(io, `${_cli.socket_id_ios}`, messageBuilder(1000, content, receiver))

                        await M('notice_task_detail').updateOne({
                            id: id,
                        }, {
                            $set: {
                                send_status: {
                                    code: 2,
                                    message: '发送成功'
                                }
                            }
                        })
                    } else {
                        await M('notice_task_detail').updateOne({
                            id: id,
                        }, {
                            $set: {
                                send_status: {
                                    code: 3,
                                    message: 'user sockets not found'
                                }
                            }
                        })
                    }
                } catch (e) {
                    log4js.error(e)
                }
            }))
        }

        return _content
    }, {
        setup: async (channel) => {
            channel.prefetch(1);
            await channel.assertQueue(im_task_queue, { durable: false });
            return im_task_queue;
        }
    })
}

exports.start = start
